package com.yeyks.app.controller.alipay;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeyks.common.em.pay.PayAttach;
import com.yeyks.common.em.pay.PayTypeEnum;
import com.yeyks.common.utils.DateUtils;
import com.yeyks.common.utils.IdWorkerUtil;
import com.yeyks.common.utils.TryCatchUtil;
import com.yeyks.commonReference.append.alipay.config.AlipayAppProperties;
import com.yeyks.commonReference.append.alipay.config.AlipayNotifyParam;
import com.yeyks.commonReference.append.mongodb.entity.PayCallbackRecordMongoEntity;
import com.yeyks.commonReference.append.mongodb.service.PayCallbackRecordMongoService;
import com.yeyks.commonReference.service.order.OrderPayRecordService;
import com.yeyks.commonReference.service.vip.MemberCardOnlineService;
import com.yeyks.commonReference.utils.PayUtil;
import com.yeyks.consumer.service.RechargeRecordService;
import com.yeyks.order.dal.domain.OrderPayRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author fuchangshuai
 * @date 2019/3/6 11:36 AM
 */
@Slf4j
@ApiIgnore
@RestController
public class AlipayCallbackController {

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    @Autowired
    private AlipayAppProperties alipayAppProperties;
    @Autowired
    private RechargeRecordService rechargeRecordService;
    @Autowired
    private OrderPayRecordService orderPayRecordService;
    @Autowired
    private PayCallbackRecordMongoService payCallbackRecordMongoService;
    @Autowired
    private MemberCardOnlineService memberCardOnlineService;

    /**
     * 订单支付回调（新版）
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/aliPayCallbackNew", method = RequestMethod.POST)
    @ResponseBody
    public String callbackNew(HttpServletRequest request) {
        Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        String paramsJson = JSON.toJSONString(params);
        TryCatchUtil.tryCatch(() -> {
            payCallbackRecordMongoService.save(new PayCallbackRecordMongoEntity()
                    .setId(IdWorkerUtil.nextStrId())
                    .setCreateDate(new Date())
                    .setType(PayTypeEnum.ALIPAY.desc())
                    .setRequestMessage(JSONUtil.toJsonStr(request.getParameterMap()))
                    .setText(paramsJson));
        });
        log.info("支付宝回调，{}", paramsJson);
        try {
            // 调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayAppProperties.getPubKey(),
                    alipayAppProperties.getCharset(), alipayAppProperties.getSignType());
            log.info("signVerified={}", signVerified);
            if (signVerified) {
                log.info("支付宝回调签名认证成功");
                // 另起线程处理业务
                log.info("另起线程处理业务");
                executorService.execute(() -> disposeWork(params));
                // 如果签名验证正确，立即返回success，后续业务另起线程单独处理
                return "success";
            } else {
                log.info("支付宝回调签名认证失败, paramsJson:{}", paramsJson);
                return "failure";
            }
        } catch (AlipayApiException e) {
            log.info("支付宝回调发生异常{}", e.getLocalizedMessage());
            return "failure";
        }
    }

    //处理业务
    private void disposeWork(Map<String, String> params) {
        AlipayNotifyParam param = buildAlipayNotifyParam(params);
        String tradeStatus = param.getTradeStatus();
        String attach = param.getPassbackParams();
//        String payType;
//        String payMethod = "";
//        boolean newFlag = true;
//        try {
//            Map<String, String> attachMap = PayUtil.getAttach(attach);
//            payType = attachMap.get("payType");
//            payMethod = attachMap.get("payMethod");
//        } catch (Exception e) {
//            payType = attach;
//            newFlag = false;
//        }
        Map<String, String> attachMap = PayUtil.getAttach(attach);
        String orderType = attachMap.get("orderType");
        String payType = attachMap.get("payType");
        boolean flag = false;
        // 支付成功
        if (tradeStatus.equals("TRADE_SUCCESS")) {
            log.info("支付成功");
            flag = true;
        } else {
            log.info("支付失败");
        }
        //订单支付
        if (PayAttach.ORDER_PAY.desc().equals(orderType)) {
//            if (newFlag) {
            orderPayRecordService.payCallback(param.getOutTradeNo(), PayTypeEnum.getEnumFromDesc(payType), flag);
//            } else {
//                unifyPayCallbackService.payCallback(param.getOutTradeNo(), flag);
//            }
            updateOrderPayRecord(param, payType, flag);
        }
        //会员卡支付
        if (PayAttach.CARD_PAY.desc().equals(orderType)) {
            rechargeRecordService.payCardCallback(param.getOutTradeNo(), flag);
        }
        //黑鱼礼包支付
        if (PayAttach.BAG_GIFT_PAY.desc().equals(orderType)) {
            rechargeRecordService.paySmallBlackFishSpreeCallback(param.getOutTradeNo(), flag);
        }
        //会员卡enable支付(线上)v3.8.3
        else if (PayAttach.MEMBER_CARD_ENABLE_ORDER_ONLINE.desc().equals(orderType)) {
            String outTradeNo = param.getOutTradeNo();
//            if (newFlag) {
            //处理小程序订单,小程序订单以xcx结尾
            String desc = PayTypeEnum.XCX.desc();
            int xcxFlag = outTradeNo.indexOf(desc);
            if (xcxFlag > -1) {
                outTradeNo = outTradeNo.substring(0, xcxFlag);
            }
            memberCardOnlineService.payCallback(outTradeNo, PayTypeEnum.getEnumFromDesc(payType), param, flag);
        }
    }

    //跟新订单支付记录状态
    private void updateOrderPayRecord(AlipayNotifyParam param, String payType, Boolean paySuccess) {
        try {
            OrderPayRecord record = orderPayRecordService.getOne(new QueryWrapper<OrderPayRecord>()
                    .eq(OrderPayRecord.ORDER_NO, param.getOutTradeNo()).eq(OrderPayRecord.PAY_TYPE, payType));
            //旧的 待删--------------------
//            if (record == null) {
//                record = orderPayRecordService.selectOrderNo(param.getOutTradeNo());
//            }
            //-------------------------
            if (record == null) {
                return;
            }
            String timeEnd = DateUtils.formatYMDHMSStr(param.getGmtPayment());
            record.setFinishTime(timeEnd);
            record.setPayReturnNo(param.getTradeNo());
            record.setPayResult(param.getTradeStatus());
            if (paySuccess) {
                record.setStatus("付款成功");
            } else {
                record.setStatus("付款超时");
            }
            orderPayRecordService.update(record);
        } catch (Exception e) {
            log.error("支付宝支付回调修改支付记录失败{}", e.getLocalizedMessage());
            e.printStackTrace();
        }
    }

    // 将request中的参数转换成Map
    private Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<>();
        //1.从支付宝回调的request域中取值
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < values.length; i++) {
                if ((i == values.length - 1)) {
                    stringBuilder.append(values[i]);
                } else {
                    stringBuilder.append(values[i] + ",");
                }
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            retMap.put(name, stringBuilder.toString());
        }
        return retMap;
    }

    private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSON.toJSONString(params);
        return JSON.parseObject(json, AlipayNotifyParam.class);
    }

}
